U-Net

In [1]:
# Imports
import os
from keras.layers import *
from keras.models import Model, load_model
from keras.regularizers import l2
from keras.callbacks import ModelCheckpoint
from keras.optimizers import RMSprop, Adam, SGD
import matplotlib.pyplot as plt
import scipy.misc as m
/home/augusto/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:34: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters
Using TensorFlow backend.

Model

In [2]:
def UNet(n):
    inp = Input(shape=(None,None,3))
    
    conv = [inp]
    pool = [inp]
    
    # Contracting path
    for i in range(1, n):
        conv.append(Conv2D(16*2**i, (3,3), activation='relu', data_format='channels_last', padding='same')(pool[i-1]))
        conv[i] = Dropout(0.2)(conv[i])
        conv[i] = Conv2D(16*2**i, (3,3), activation='relu', data_format='channels_last', padding='same')(conv[i])
        pool.append(MaxPooling2D((2,2), data_format='channels_last')(conv[i]))

    conv.append(Conv2D(16*2**n, (3,3), activation='relu', data_format='channels_last', padding='same')(pool[n-1]))
    conv[n] = Conv2D(16*2**n, (3,3), activation='relu', data_format='channels_last', padding='same')(conv[n])
    convUp = conv[n]

    # Expanding path
    for i in range(n-1, 0, -1):
        up = UpSampling2D(size=(2,2))(convUp)
        up = concatenate([up, conv[i]], axis=3)
        convUp = Conv2D(16*2**i, (3,3), activation='relu', data_format='channels_last', padding='same')(up)
        convUp = Dropout(0.2)(convUp)
        convUp = Conv2D(16*2**i, (3,3), activation='relu', data_format='channels_last', padding='same')(convUp)
        
    last_conv = Conv2D(2, (1,1), activation='softmax', data_format='channels_last', padding='same')(convUp)

    model = Model(inputs=inp, outputs=last_conv)
    
    return model
In [3]:
unet = UNet(3)
unet.summary()
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            (None, None, None, 3 0                                            
__________________________________________________________________________________________________
conv2d_1 (Conv2D)               (None, None, None, 3 896         input_1[0][0]                    
__________________________________________________________________________________________________
dropout_1 (Dropout)             (None, None, None, 3 0           conv2d_1[0][0]                   
__________________________________________________________________________________________________
conv2d_2 (Conv2D)               (None, None, None, 3 9248        dropout_1[0][0]                  
__________________________________________________________________________________________________
max_pooling2d_1 (MaxPooling2D)  (None, None, None, 3 0           conv2d_2[0][0]                   
__________________________________________________________________________________________________
conv2d_3 (Conv2D)               (None, None, None, 6 18496       max_pooling2d_1[0][0]            
__________________________________________________________________________________________________
dropout_2 (Dropout)             (None, None, None, 6 0           conv2d_3[0][0]                   
__________________________________________________________________________________________________
conv2d_4 (Conv2D)               (None, None, None, 6 36928       dropout_2[0][0]                  
__________________________________________________________________________________________________
max_pooling2d_2 (MaxPooling2D)  (None, None, None, 6 0           conv2d_4[0][0]                   
__________________________________________________________________________________________________
conv2d_5 (Conv2D)               (None, None, None, 1 73856       max_pooling2d_2[0][0]            
__________________________________________________________________________________________________
conv2d_6 (Conv2D)               (None, None, None, 1 147584      conv2d_5[0][0]                   
__________________________________________________________________________________________________
up_sampling2d_1 (UpSampling2D)  (None, None, None, 1 0           conv2d_6[0][0]                   
__________________________________________________________________________________________________
concatenate_1 (Concatenate)     (None, None, None, 1 0           up_sampling2d_1[0][0]            
                                                                 conv2d_4[0][0]                   
__________________________________________________________________________________________________
conv2d_7 (Conv2D)               (None, None, None, 6 110656      concatenate_1[0][0]              
__________________________________________________________________________________________________
dropout_3 (Dropout)             (None, None, None, 6 0           conv2d_7[0][0]                   
__________________________________________________________________________________________________
conv2d_8 (Conv2D)               (None, None, None, 6 36928       dropout_3[0][0]                  
__________________________________________________________________________________________________
up_sampling2d_2 (UpSampling2D)  (None, None, None, 6 0           conv2d_8[0][0]                   
__________________________________________________________________________________________________
concatenate_2 (Concatenate)     (None, None, None, 9 0           up_sampling2d_2[0][0]            
                                                                 conv2d_2[0][0]                   
__________________________________________________________________________________________________
conv2d_9 (Conv2D)               (None, None, None, 3 27680       concatenate_2[0][0]              
__________________________________________________________________________________________________
dropout_4 (Dropout)             (None, None, None, 3 0           conv2d_9[0][0]                   
__________________________________________________________________________________________________
conv2d_10 (Conv2D)              (None, None, None, 3 9248        dropout_4[0][0]                  
__________________________________________________________________________________________________
conv2d_11 (Conv2D)              (None, None, None, 2 66          conv2d_10[0][0]                  
==================================================================================================
Total params: 471,586
Trainable params: 471,586
Non-trainable params: 0
__________________________________________________________________________________________________

DRIVE

Read image names

In [4]:
dir_drive = "/home/augusto/tmp/datasets/drive/training/"
dir_img = dir_drive + "images/"
dir_seg = dir_drive + "1st_manual/"
dir_test = "/home/augusto/tmp/datasets/drive/test/"
dir_test_img = dir_test + "images/"
dir_test_seg = dir_test + "1st_manual/"

with open(dir_drive + 'train.txt') as f:
    x = f.read().splitlines()
imgs = np.array(x)

with open(dir_drive + 'val.txt') as f:
    x = f.read().splitlines()
val_imgs = np.array(x)

with open(dir_test + 'test.txt') as f:
    x = f.read().splitlines()
test_imgs = np.array(x)

print(imgs[0])
21_training.tif 21_manual1.gif 21_training_mask.gif

Load data

In [5]:
def extract_patches(img, size):
    H, W, *c = img.shape
    h = H//size[0]
    w = W//size[1]
    patches = []
    for i in range(h):
        for j in range(w):
            patches.append(img[i*size[0]:(i+1)*size[0], j*size[1]:(j+1)*size[1]])
    return np.array(patches)

def to_categorical(patches):
    n, H, W = patches.shape
    segmentation = np.zeros((n,H,W,2))
    for i in range(n):
        segmentation[i,:,:,0] = (patches[i,:,:] == 0).astype(int)
        segmentation[i,:,:,1] = (patches[i,:,:] > 0).astype(int)
    return segmentation
In [6]:
images = []
gt = []
for line in imgs:
    names = line.split(' ')
    images.append(m.imread(dir_img + names[0]))
    gt.append(m.imread(dir_seg + names[1]))
images = np.array(images)
In [7]:
patch_size = 32

X_train = []
y_train = []
for i, img in enumerate(images):
    seg_img = gt[i]
    X_train.append(extract_patches(img, (patch_size, patch_size)))
    y_patches = to_categorical(extract_patches(seg_img, (patch_size,patch_size)))
    y_train.append(y_patches)
    
    fig = plt.figure(figsize=(20,40))
    ax = fig.add_subplot(1,2,1)
    ax.imshow(img)
    ax.set_title("original image")
    
    ax = fig.add_subplot(1,2,2)
    ax.imshow(seg_img, cmap='gray')
    ax.set_title('ground truth')
    
    plt.show()
In [8]:
X_train = np.array(X_train)
X_train = np.reshape(X_train, (-1, patch_size,patch_size,3))
y_train = np.array(y_train)
y_train = np.reshape(y_train, (-1, patch_size, patch_size,2))
print(X_train.shape, y_train.shape)
(6120, 32, 32, 3) (6120, 32, 32, 2)
In [9]:
X_val = []
y_val = []
for line in val_imgs:
    names = line.split(' ')
    val_img = m.imread(dir_img + names[0])
    val_seg = m.imread(dir_seg + names[1])
    X_val.append(extract_patches(val_img, (patch_size, patch_size)))
    y_patches = to_categorical(extract_patches(val_seg, (patch_size,patch_size)))
    y_val.append(y_patches)
    
X_val, y_val = np.array(X_val), np.array(y_val)
X_val = np.reshape(X_val, (-1, patch_size, patch_size, 3))
y_val = np.reshape(y_val, (-1, patch_size, patch_size, 2))
print(X_val.shape, y_val.shape)
(1224, 32, 32, 3) (1224, 32, 32, 2)
In [10]:
n = 100
fig = plt.figure(figsize=(5,10))
ax = fig.add_subplot(1,2,1)
ax.imshow(X_train[n][:,:])
ax.set_title('img')

ax = fig.add_subplot(1,2,2)
ax.imshow(y_train[n][:,:,1], cmap='gray')
ax.set_title('gt')

plt.show()

Training

In [11]:
opt = Adam(lr=1e-4)

unet.compile(loss='binary_crossentropy',
             optimizer=opt,
             metrics=['accuracy'])

checkpoint = ModelCheckpoint('weights/unet_drive.hdf5', monitor='val_loss', verbose=1, save_best_only=True, mode='min')
In [12]:
# unet.fit(X_train, y_train,
#           validation_data=(X_val, y_val),
#           epochs=60, batch_size=8,
#           verbose=2,
#           callbacks=[checkpoint])

# unet.save('models/unet_drive.h5')

unet = load_model('models/unet_drive.h5')

Predictions on test set

In [13]:
X_test = []
y_test = []
for line in test_imgs:
    names = line.split()
    test_img = m.imread(dir_test_img + names[0])
    test_seg = m.imread(dir_test_seg + names[1])
    X_test.append(test_img)
    y_ing = to_categorical(np.array([test_seg]))
    y_test.append(y_ing)
In [14]:
y_test = np.array(y_test)
y_test = np.squeeze(y_test)
X_test = np.array(X_test)
print(X_test.shape, y_test.shape)
(20, 584, 565, 3) (20, 584, 565, 2)
In [23]:
y_pred = unet.predict(X_test[:10,:,:-1,:])
y_pred2 = unet.predict(X_test[10:,:,:-1,:])
y_pred = np.concatenate((y_pred, y_pred2),axis=0)
y_predi = np.argmax(y_pred, axis=3)
y_testi = np.argmax(y_test[:,:,:-1,:], axis=3)
print(y_testi.shape,y_predi.shape)
(20, 584, 564) (20, 584, 564)
In [25]:
gtp = (y_testi == 1).astype(int)
pp = (y_predi == 1).astype(int)
gtn = (y_testi == 0).astype(int)
pn = (y_predi == 0).astype(int)

TP = (gtp*pp).sum()
TN = (gtn*pn).sum()
FP = (gtn*pp).sum()
FN = (gtp*pn).sum()

Precision = TP/(TP+FP)
Sensitivity = TP/(TP+FN)
FMeasure = (2 * Precision*Sensitivity)/(Precision + Sensitivity)
print(Precision, Sensitivity, FMeasure)
0.8355382590964837 0.775658583429219
In [26]:
shape = (584, 565)
n_classes= 1

for i in range(10):
    img_is  = X_test[i]
    seg = y_predi[i]
    segtest = y_testi[i]

    fig = plt.figure(figsize=(20,40))    
    ax = fig.add_subplot(1,3,1)
    ax.imshow(img_is, cmap='gray')
    ax.set_title("original")
    
    ax = fig.add_subplot(1,3,2)
    ax.imshow(seg, cmap='gray')
    ax.set_title("predicted class")
    
    ax = fig.add_subplot(1,3,3)
    ax.imshow(segtest, cmap='gray')
    ax.set_title("true class")
    plt.show()
        
#     m.imsave('images/drive/'+str(i)+'_orig.png', img_is)
    m.imsave('images/drive/'+str(i)+'_pred_unet.png', seg)
#     m.imsave('images/drive/'+str(i)+'_segm.png', segtest)
In [32]:
def calc_rates(pred, gt):
    gtp = (gt >= 1).astype(int)
    pp = (pred >= 1).astype(int)
    gtn = (gt == 0).astype(int)
    pn = (pred == 0).astype(int)
   
    TP = (gtp*pp).sum()
    TN = (gtn*pn).sum()
    FP = (gtn*pp).sum()
    FN = (gtp*pn).sum()   
    return TP, TN, FP, FN


def precision(pred, gt):
    TP, TN, FP, FN = calc_rates(pred, gt)
    return TP/(TP+FP)


def recall(pred, gt):
    TP, TN, FP, FN = calc_rates(pred, gt)
    return TP/(TP+FN)


def FM(prediction, ground_truth):
    P = precision(prediction, ground_truth)
    R = recall(prediction, ground_truth)
    F = (2*P*R)/(P+R)
    return F

test_gt = y_testi
P = precision(y_predi, test_gt)
R = recall(y_predi, test_gt)
F = FM(y_predi, test_gt)

print(P, R, F)
0.8355382590964837 0.775658583429219 0.8044857156444627

DIBCO

Load images and display

In [33]:
dir_dibco = "/home/augusto/tmp/scratch/DIBCO/"

with open(dir_dibco + 'train.txt') as f:
    x = f.read().splitlines()
imgs = np.array(x)

with open(dir_dibco + 'val.txt') as f:
    x = f.read().splitlines()
val_imgs = np.array(x)

with open(dir_dibco + 'test.txt') as f:
    x = f.read().splitlines()
test_imgs = np.array(x)

print(imgs[0])
2009/H01.bmp 2009/H01.tiff

Load data

In [34]:
images = []
gt = []
for line in imgs:
    names = line.split()
    images.append(m.imread(dir_dibco + names[0], mode='RGB'))
    gt.append(m.imread(dir_dibco + names[1], mode='L'))
images = np.array(images)
gt = np.array(gt)
In [39]:
patch_size = 32

X_train = []
y_train = []
for i, img in enumerate(images):
    seg_img = gt[i]
    X_train.append(extract_patches(img, (patch_size, patch_size)))
    y_patches = to_categorical(extract_patches(seg_img, (patch_size, patch_size)))
    y_train.append(y_patches)
    
    fig = plt.figure(figsize=(20,40))
    ax = fig.add_subplot(1,2,1)
    ax.imshow(img)
    ax.set_title("original image")
    
    ax = fig.add_subplot(1,2,2)
    ax.imshow(seg_img, cmap='gray')
    ax.set_title('ground truth')
    
    plt.show()
    
print(len(X_train))
IOPub data rate exceeded.
The notebook server will temporarily stop sending output
to the client in order to avoid crashing it.
To change this limit, set the config variable
`--NotebookApp.iopub_data_rate_limit`.
86
In [41]:
X_train = np.array(X_train)
X_train = np.vstack(X_train)
X_train = np.reshape(X_train, (-1, patch_size,patch_size,3))
y_train = np.array(y_train)
y_train = np.vstack(y_train)
y_train = np.reshape(y_train, (-1, patch_size, patch_size,2))
print(X_train.shape, y_train.shape)
(90210, 32, 32, 3) (90210, 32, 32, 2)
In [42]:
X_val = []
y_val = []
for line in val_imgs:
    names = line.split()
    val_img = m.imread(dir_dibco + names[0], mode='RGB')
    val_seg = m.imread(dir_dibco + names[1], mode='L')
    X_val.append(extract_patches(val_img, (patch_size, patch_size)))
    y_patches = to_categorical(extract_patches(val_seg, (patch_size,patch_size)))
    y_val.append(y_patches)
    
X_val, y_val = np.array(X_val), np.array(y_val)
X_val = np.vstack(X_val)
X_val = np.reshape(X_val, (-1, patch_size, patch_size, 3))
y_val = np.vstack(y_val)
y_val = np.reshape(y_val, (-1, patch_size, patch_size, 2))
print(X_val.shape, y_val.shape)
(31011, 32, 32, 3) (31011, 32, 32, 2)
In [43]:
n = 533
fig = plt.figure(figsize=(5,10))
ax = fig.add_subplot(1,2,1)
ax.imshow(X_train[n][:,:])
ax.set_title('img')

ax = fig.add_subplot(1,2,2)
ax.imshow(y_train[n][:,:,1], cmap='gray')
ax.set_title('gt')

plt.show()

Training

In [44]:
opt = Adam(lr=1e-4)

unet.compile(loss='binary_crossentropy',
             optimizer=opt,
             metrics=['accuracy'])

checkpoint = ModelCheckpoint('weights/unet_dibco.hdf5', monitor='val_loss', verbose=1, save_best_only=True, mode='min')
In [45]:
# unet.fit(X_train, y_train,
#           validation_data=(X_val, y_val),
#           epochs=60, batch_size=32,
#           verbose=2,
#           callbacks=[checkpoint])

# unet.save('models/unet_dibco.h5')

unet = load_model('models/unet_dibco.h5')
Train on 90210 samples, validate on 31011 samples
Epoch 1/60
 - 72s - loss: 0.0742 - acc: 0.9782 - val_loss: 0.0850 - val_acc: 0.9638

Epoch 00001: val_loss improved from inf to 0.08495, saving model to weights/unet_dibco.hdf5
Epoch 2/60
 - 71s - loss: 0.0294 - acc: 0.9888 - val_loss: 0.0683 - val_acc: 0.9733

Epoch 00002: val_loss improved from 0.08495 to 0.06830, saving model to weights/unet_dibco.hdf5
Epoch 3/60
 - 71s - loss: 0.0253 - acc: 0.9904 - val_loss: 0.0499 - val_acc: 0.9813

Epoch 00003: val_loss improved from 0.06830 to 0.04986, saving model to weights/unet_dibco.hdf5
Epoch 4/60
 - 72s - loss: 0.0232 - acc: 0.9912 - val_loss: 0.0508 - val_acc: 0.9808

Epoch 00004: val_loss did not improve from 0.04986
Epoch 5/60
 - 72s - loss: 0.0215 - acc: 0.9919 - val_loss: 0.0760 - val_acc: 0.9696

Epoch 00005: val_loss did not improve from 0.04986
Epoch 6/60
 - 72s - loss: 0.0201 - acc: 0.9923 - val_loss: 0.0510 - val_acc: 0.9811

Epoch 00006: val_loss did not improve from 0.04986
Epoch 7/60
 - 72s - loss: 0.0190 - acc: 0.9927 - val_loss: 0.0446 - val_acc: 0.9831

Epoch 00007: val_loss improved from 0.04986 to 0.04455, saving model to weights/unet_dibco.hdf5
Epoch 8/60
 - 72s - loss: 0.0183 - acc: 0.9930 - val_loss: 0.0484 - val_acc: 0.9826

Epoch 00008: val_loss did not improve from 0.04455
Epoch 9/60
 - 71s - loss: 0.0174 - acc: 0.9933 - val_loss: 0.0475 - val_acc: 0.9829

Epoch 00009: val_loss did not improve from 0.04455
Epoch 10/60
 - 72s - loss: 0.0170 - acc: 0.9935 - val_loss: 0.0474 - val_acc: 0.9830

Epoch 00010: val_loss did not improve from 0.04455
Epoch 11/60
 - 72s - loss: 0.0163 - acc: 0.9937 - val_loss: 0.0518 - val_acc: 0.9815

Epoch 00011: val_loss did not improve from 0.04455
Epoch 12/60
 - 72s - loss: 0.0158 - acc: 0.9939 - val_loss: 0.0443 - val_acc: 0.9842

Epoch 00012: val_loss improved from 0.04455 to 0.04434, saving model to weights/unet_dibco.hdf5
Epoch 13/60
 - 72s - loss: 0.0155 - acc: 0.9940 - val_loss: 0.0664 - val_acc: 0.9734

Epoch 00013: val_loss did not improve from 0.04434
Epoch 14/60
 - 72s - loss: 0.0151 - acc: 0.9942 - val_loss: 0.0448 - val_acc: 0.9839

Epoch 00014: val_loss did not improve from 0.04434
Epoch 15/60
 - 72s - loss: 0.0145 - acc: 0.9944 - val_loss: 0.0471 - val_acc: 0.9835

Epoch 00015: val_loss did not improve from 0.04434
Epoch 16/60
 - 72s - loss: 0.0142 - acc: 0.9945 - val_loss: 0.0543 - val_acc: 0.9807

Epoch 00016: val_loss did not improve from 0.04434
Epoch 17/60
 - 72s - loss: 0.0139 - acc: 0.9946 - val_loss: 0.0447 - val_acc: 0.9839

Epoch 00017: val_loss did not improve from 0.04434
Epoch 18/60
 - 73s - loss: 0.0137 - acc: 0.9946 - val_loss: 0.0462 - val_acc: 0.9839

Epoch 00018: val_loss did not improve from 0.04434
Epoch 19/60
 - 72s - loss: 0.0134 - acc: 0.9947 - val_loss: 0.0511 - val_acc: 0.9829

Epoch 00019: val_loss did not improve from 0.04434
Epoch 20/60
 - 72s - loss: 0.0131 - acc: 0.9949 - val_loss: 0.0457 - val_acc: 0.9846

Epoch 00020: val_loss did not improve from 0.04434
Epoch 21/60
 - 73s - loss: 0.0132 - acc: 0.9948 - val_loss: 0.0493 - val_acc: 0.9830

Epoch 00021: val_loss did not improve from 0.04434
Epoch 22/60
 - 72s - loss: 0.0128 - acc: 0.9950 - val_loss: 0.0464 - val_acc: 0.9846

Epoch 00022: val_loss did not improve from 0.04434
Epoch 23/60
 - 73s - loss: 0.0125 - acc: 0.9951 - val_loss: 0.0465 - val_acc: 0.9843

Epoch 00023: val_loss did not improve from 0.04434
Epoch 24/60
 - 73s - loss: 0.0125 - acc: 0.9951 - val_loss: 0.0473 - val_acc: 0.9838

Epoch 00024: val_loss did not improve from 0.04434
Epoch 25/60
 - 72s - loss: 0.0123 - acc: 0.9952 - val_loss: 0.0471 - val_acc: 0.9853

Epoch 00025: val_loss did not improve from 0.04434
Epoch 26/60
 - 73s - loss: 0.0121 - acc: 0.9952 - val_loss: 0.0474 - val_acc: 0.9844

Epoch 00026: val_loss did not improve from 0.04434
Epoch 27/60
 - 73s - loss: 0.0118 - acc: 0.9953 - val_loss: 0.0492 - val_acc: 0.9845

Epoch 00027: val_loss did not improve from 0.04434
Epoch 28/60
 - 73s - loss: 0.0117 - acc: 0.9954 - val_loss: 0.0513 - val_acc: 0.9838

Epoch 00028: val_loss did not improve from 0.04434
Epoch 29/60
 - 73s - loss: 0.0117 - acc: 0.9954 - val_loss: 0.0481 - val_acc: 0.9849

Epoch 00029: val_loss did not improve from 0.04434
Epoch 30/60
 - 72s - loss: 0.0115 - acc: 0.9955 - val_loss: 0.0594 - val_acc: 0.9829

Epoch 00030: val_loss did not improve from 0.04434
Epoch 31/60
 - 73s - loss: 0.0112 - acc: 0.9955 - val_loss: 0.0524 - val_acc: 0.9838

Epoch 00031: val_loss did not improve from 0.04434
Epoch 32/60
 - 73s - loss: 0.0113 - acc: 0.9955 - val_loss: 0.0494 - val_acc: 0.9844

Epoch 00032: val_loss did not improve from 0.04434
Epoch 33/60
 - 74s - loss: 0.0112 - acc: 0.9956 - val_loss: 0.0508 - val_acc: 0.9847

Epoch 00033: val_loss did not improve from 0.04434
Epoch 34/60
 - 73s - loss: 0.0109 - acc: 0.9956 - val_loss: 0.0498 - val_acc: 0.9845

Epoch 00034: val_loss did not improve from 0.04434
Epoch 35/60
 - 73s - loss: 0.0110 - acc: 0.9956 - val_loss: 0.0537 - val_acc: 0.9834

Epoch 00035: val_loss did not improve from 0.04434
Epoch 36/60
 - 73s - loss: 0.0108 - acc: 0.9957 - val_loss: 0.0536 - val_acc: 0.9844

Epoch 00036: val_loss did not improve from 0.04434
Epoch 37/60
 - 73s - loss: 0.0108 - acc: 0.9957 - val_loss: 0.0545 - val_acc: 0.9837

Epoch 00037: val_loss did not improve from 0.04434
Epoch 38/60
 - 73s - loss: 0.0106 - acc: 0.9958 - val_loss: 0.0557 - val_acc: 0.9829

Epoch 00038: val_loss did not improve from 0.04434
Epoch 39/60
 - 73s - loss: 0.0106 - acc: 0.9958 - val_loss: 0.0529 - val_acc: 0.9844

Epoch 00039: val_loss did not improve from 0.04434
Epoch 40/60
 - 73s - loss: 0.0106 - acc: 0.9958 - val_loss: 0.0589 - val_acc: 0.9836

Epoch 00040: val_loss did not improve from 0.04434
Epoch 41/60
 - 73s - loss: 0.0105 - acc: 0.9958 - val_loss: 0.0521 - val_acc: 0.9844

Epoch 00041: val_loss did not improve from 0.04434
Epoch 42/60
 - 73s - loss: 0.0102 - acc: 0.9959 - val_loss: 0.0569 - val_acc: 0.9834

Epoch 00042: val_loss did not improve from 0.04434
Epoch 43/60
 - 73s - loss: 0.0105 - acc: 0.9958 - val_loss: 0.0638 - val_acc: 0.9813

Epoch 00043: val_loss did not improve from 0.04434
Epoch 44/60
 - 73s - loss: 0.0101 - acc: 0.9959 - val_loss: 0.0541 - val_acc: 0.9844

Epoch 00044: val_loss did not improve from 0.04434
Epoch 45/60
 - 73s - loss: 0.0101 - acc: 0.9959 - val_loss: 0.0527 - val_acc: 0.9839

Epoch 00045: val_loss did not improve from 0.04434
Epoch 46/60
 - 74s - loss: 0.0100 - acc: 0.9960 - val_loss: 0.0572 - val_acc: 0.9845

Epoch 00046: val_loss did not improve from 0.04434
Epoch 47/60
 - 73s - loss: 0.0100 - acc: 0.9960 - val_loss: 0.0606 - val_acc: 0.9844

Epoch 00047: val_loss did not improve from 0.04434
Epoch 48/60
 - 73s - loss: 0.0100 - acc: 0.9960 - val_loss: 0.0603 - val_acc: 0.9841

Epoch 00048: val_loss did not improve from 0.04434
Epoch 49/60
 - 73s - loss: 0.0099 - acc: 0.9960 - val_loss: 0.0553 - val_acc: 0.9843

Epoch 00049: val_loss did not improve from 0.04434
Epoch 50/60
 - 73s - loss: 0.0098 - acc: 0.9960 - val_loss: 0.0527 - val_acc: 0.9848

Epoch 00050: val_loss did not improve from 0.04434
Epoch 51/60
 - 73s - loss: 0.0098 - acc: 0.9961 - val_loss: 0.0583 - val_acc: 0.9836

Epoch 00051: val_loss did not improve from 0.04434
Epoch 52/60
 - 73s - loss: 0.0096 - acc: 0.9961 - val_loss: 0.0589 - val_acc: 0.9837

Epoch 00052: val_loss did not improve from 0.04434
Epoch 53/60
 - 73s - loss: 0.0097 - acc: 0.9961 - val_loss: 0.0523 - val_acc: 0.9845

Epoch 00053: val_loss did not improve from 0.04434
Epoch 54/60
 - 73s - loss: 0.0096 - acc: 0.9961 - val_loss: 0.0583 - val_acc: 0.9846

Epoch 00054: val_loss did not improve from 0.04434
Epoch 55/60
 - 73s - loss: 0.0096 - acc: 0.9961 - val_loss: 0.0583 - val_acc: 0.9846

Epoch 00055: val_loss did not improve from 0.04434
Epoch 56/60
 - 73s - loss: 0.0095 - acc: 0.9962 - val_loss: 0.0574 - val_acc: 0.9846

Epoch 00056: val_loss did not improve from 0.04434
Epoch 57/60
 - 74s - loss: 0.0095 - acc: 0.9962 - val_loss: 0.0566 - val_acc: 0.9837

Epoch 00057: val_loss did not improve from 0.04434
Epoch 58/60
 - 73s - loss: 0.0093 - acc: 0.9962 - val_loss: 0.0612 - val_acc: 0.9844

Epoch 00058: val_loss did not improve from 0.04434
Epoch 59/60
 - 73s - loss: 0.0096 - acc: 0.9962 - val_loss: 0.0545 - val_acc: 0.9847

Epoch 00059: val_loss did not improve from 0.04434
Epoch 60/60
 - 73s - loss: 0.0091 - acc: 0.9963 - val_loss: 0.0528 - val_acc: 0.9853

Epoch 00060: val_loss did not improve from 0.04434

Predictions on test set

In [46]:
def crop(img, mult):
    H, W, *c = img.shape
    h = H - H%mult
    w = W - W%mult
    return img[:h,:w]
    
X_test = []
y_test = []
for line in test_imgs:
    names = line.split()
    test_img = m.imread(dir_dibco + names[0], mode='RGB')
    test_seg = m.imread(dir_dibco + names[1], mode='L')
    X_test.append(crop(test_img, 4))
    y_ing = to_categorical(np.array([test_seg]))
    y_test.append(crop(y_ing[0], 4))
In [47]:
y_predi = []
y_testi = []
for i, ing in enumerate(X_test):
    y_pred = unet.predict(np.asarray([ing]))
    y_predi.append(np.argmax(y_pred, axis=3))
    y_testi.append(np.argmax(y_test[i], axis=2))
In [48]:
for i, ing in enumerate(y_predi):
    gtn = (y_testi[i] == 1).astype(int)
    pn = (ing[0] == 1).astype(int)
    gtp = (y_testi[i] == 0).astype(int)
    pp = (ing[0] == 0).astype(int)

TP = (gtp*pp).sum()
TN = (gtn*pn).sum()
FP = (gtn*pp).sum()
FN = (gtp*pn).sum()

Precision = TP/(TP+FP)
Sensitivity = TP/(TP+FN)
print(Precision, Sensitivity)
0.6872385338706583 0.9821525011813947
In [49]:
for i in range(10):
    img_is  = X_test[i]
    seg = y_predi[i][0]
    segtest = y_testi[i]

    fig = plt.figure(figsize=(20,40))    
    ax = fig.add_subplot(1,3,1)
    ax.imshow(img_is, cmap='gray')
    ax.set_title("original")
    
    ax = fig.add_subplot(1,3,2)
    ax.imshow(seg, cmap='gray')
    ax.set_title("predicted class")
    
    ax = fig.add_subplot(1,3,3)
    ax.imshow(segtest, cmap='gray')
    ax.set_title("true class")
    plt.show()
    
#     m.imsave('images/dibco/'+str(i)+'_orig.png', img_is)
    m.imsave('images/dibco/'+str(i)+'_pred_unet.png', seg)
#     m.imsave('images/dibco/'+str(i)+'_segm.png', segtest)
    
    print(img_is.shape, seg.shape, segtest.shape)
(432, 1776, 3) (432, 1776) (432, 1776)
(808, 1504, 3) (808, 1504) (808, 1504)
(628, 1972, 3) (628, 1972) (628, 1972)
(508, 1012, 3) (508, 1012) (508, 1012)
(288, 1504, 3) (288, 1504) (288, 1504)
(888, 1680, 3) (888, 1680) (888, 1680)
(580, 2544, 3) (580, 2544) (580, 2544)
(920, 3932, 3) (920, 3932) (920, 3932)
(284, 1212, 3) (284, 1212) (284, 1212)
(960, 3216, 3) (960, 3216) (960, 3216)